package com.chao.base.struct;

import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
import java.util.function.Function;

/**
 * @author : Rookie
 * @description : 布隆过滤器
 * @date : 2023/10/15
 */
public class BloomFilter<T> {

    private final int size;

    private final BitSet bitSet;

    private final List<Function<T,Integer>> hashFunctions;

    public BloomFilter(int size,List<Function<T,Integer>> functions) {
        this.size = size;
        this.bitSet = new BitSet(size);
        this.hashFunctions = functions;
    }

    public void add(T t) {
        hashFunctions.forEach(function -> {
            int hash = function.apply(t) % size;
            bitSet.set(hash);
        });
    }

    public boolean contains(T t) {
        return hashFunctions.stream()
                .allMatch(function -> {
                    int hash = function.apply(t) % size;
                    return bitSet.get(hash);
                });
    }

    static class HashFunction1 implements Function<String,Integer> {

        @Override
        public Integer apply(String s) {
            int hash = 7;
            for (int i = 0; i < s.length(); i++) {
                hash = hash * 31 + s.charAt(i);
            }
            return hash;
        }
    }

    static class HashFunction2 implements Function<String,Integer> {


        @Override
        public Integer apply(String s) {
            int hash = 8610;
            for (int i = 0; i < s.length(); i++) {
                hash = (hash >>> 5) + s.charAt(i);
            }
            return hash;
        }
    }

    public static void main(String[] args) {
        HashFunction1 hashFunction1 = new HashFunction1();
        HashFunction2 hashFunction2 = new HashFunction2();
        List<Function<String, Integer>> functions = new ArrayList<>();
        functions.add(hashFunction1);
        functions.add(hashFunction2);

        BloomFilter<String> bloomFilter = new BloomFilter<>(100, functions);
        bloomFilter.add("apple");
        bloomFilter.add("huawei");

        System.out.println("是否有apple：" + bloomFilter.contains("apple"));
        System.out.println("是否有xiaomi：" + bloomFilter.contains("xiaomi"));
    }
}
